package com.boroborome.convert;

import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.text.MessageFormat;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class ConvertTool {
    public void convertNgnix(String from, String to) {
        convertLog(from, to, NgnixCallRecord::parse);
    }

    // file format: time, message
    public void convertApp(String from, String to) {
        convertLog(from, to, AppCallRecord::parse);
    }

    public void convertLog(String from, String to, Function<String[], ICallRecord> parser) {
        try (Reader fileReader = new FileReader(from);
             CSVReader csvReader = new CSVReaderBuilder(fileReader).build();
             PrintWriter writer = new PrintWriter(new FileOutputStream(to))) {
            StatisticItemCalculator calculator = new StatisticItemCalculator();
            // output title
            writer.println("log-time\turl\ttime");

            readCsvLines(csvReader)
                    .map(parser)
                    .peek(cr -> saveRecode(cr, writer))
                    .forEach(calculator::accept);

            System.out.println("FunctionId\tAvgTime\tMidTime\tMaxTime\tCount");
            calculator.statisticItemStream()
                    .sorted(Comparator.comparing(StatisticItem::getAvgTime))
                    .forEach(this::showStatisticItems);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void showStatisticItems(StatisticItem item) {
        System.out.println(MessageFormat.format("{0}\t{1}\t{2}\t{3}\t{4}",
                item.getUrl(), item.getAvgTime(), item.getMidTime(), item.getMaxTime(), item.getCount()));
    }

    private void saveRecode(ICallRecord cr, PrintWriter writer) {
        writer.println(String.join("\t",
                String.valueOf(cr.getLogTime()),
                cr.getFunctionId(),
                String.valueOf(cr.getTime())));
    }

    private Stream<String[]> readCsvLines(CSVReader csvReader) {
        // ignore title
        Iterator<String[]> lineIt = csvReader.iterator();
        if (lineIt.hasNext()) {
            lineIt.next();
        }
        return StreamSupport.stream(new Spliterators.AbstractSpliterator<String[]>(0, 0) {
            @Override
            public boolean tryAdvance(Consumer<? super String[]> action) {
                if (lineIt.hasNext()) {
                    action.accept(lineIt.next());
                    return true;
                }
                return false;
            }
        }, false);
    }

}
